package com.whzm.service.Impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.TradeFundBill;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.builder.AlipayTradeQueryRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.model.result.AlipayF2FQueryResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.utils.Utils;
import com.whzm.config.ExpiraionMessagePostProcessor;
import com.whzm.mapper.MemberInfoMapper;
import com.whzm.mapper.MemberOrderMapper;
import com.whzm.mapper.MemberTypeMapper;
import com.whzm.pojo.MemberInfo;
import com.whzm.pojo.MemberOrder;
import com.whzm.pojo.MemberType;
import com.whzm.service.MemberInfoService;
import com.whzm.util.ResponseEntity;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class MemberInfoServiceImpl implements MemberInfoService {
    @Autowired
    MemberInfoMapper memberInfoMapper;
    @Autowired
    MemberTypeMapper memberTypeMapper;
    @Autowired
    MemberOrderMapper memberOrderMapper;
    @Autowired
    RabbitTemplate rabbitTemplate;


    /**获取当前用户订单*/
    @Override
    @Transactional(readOnly = true)
    public ResponseEntity getListByUserId(MemberOrder memberOrder, String userId) {
        if(!StringUtils.isEmpty(memberOrder)) {
            //执行查询
            List<MemberOrder>lists=memberOrderMapper.getListByUserId(userId);
            //数据封装
            return ResponseEntity.entitySuccess(1,"1",lists);
        }
        return ResponseEntity.entitySuccess(0,"0",null);
    }

    /**支付宝回调请求
     * @param request
     * @return*/
    @Override
    public String lipayCallback(HttpServletRequest request) {
        //1.从request对象中取出所有的请求参数
        Map requestParams = request.getParameterMap();
        //2.遍历map集合中的数据
        Map<String,String> params = new HashMap<>();
        for(Iterator iter = requestParams.keySet().iterator(); iter.hasNext();){
            String name = (String)iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for(int i = 0 ; i <values.length;i++){
                valueStr = (i == values.length -1)?valueStr + values[i]:valueStr + values[i]+",";
            }
            //把request对象中的数据存放到map集合找那个
            params.put(name,valueStr);
        }
        params.forEach((k,v) ->{
            System.out.println(k+":"+v);
        });
        //非常重要,验证回调的正确性,是不是支付宝发的.并且呢还要避免重复通知.
        params.remove("sign_type");
        try {
            //验证签
            boolean alipayRSACheckedV2 = AlipaySignature.rsaCheckV2(params, Configs.getAlipayPublicKey(),"utf-8", Configs.getSignType());

            if(!alipayRSACheckedV2){
                System.out.println("非法请求,验证不通过,再恶意请求我就报警找网警了");
                return "failed";
            }
        } catch (AlipayApiException e) {
            System.out.println("支付宝验证回调异常"+e);
            return "failed";
        }

        //1.判断交易状态是否成功
        String trade_status = params.get("trade_status");
        //String trade_status = requset.getTrade_status();
        if(!trade_status.equals("TRADE_SUCCESS")){//如果交易状态不为TRADE_SUCCESS就表示交易失败
            return "failed";

        }
        //2.把数据库中订单号的交易状态改为1
        //取出订单编号
        String orderNo = params.get("out_trade_no");
        // String orderNo = requset.getOut_trade_no();
        //生效
        String status="1";
        Integer result = memberOrderMapper.updateStatus(orderNo,status);
        if(result > 0){
            //获取订单信息
            MemberOrder memberOrder=memberOrderMapper.getOrderById(orderNo);
            //当前时间
            LocalDate nowdate = LocalDate.now();
            //查看关联信息表，无则创建创建信息表
            MemberInfo memberInfo=memberInfoMapper.getMemberInfoByUserId(memberOrder.getUserId());
            if(StringUtils.isEmpty(memberInfo)) {
                String id = "R" + (System.currentTimeMillis() + "" + (int) (Math.random() * 100)).substring(3);
                //memberinfo创建时间默认，status为0失效,1生效，
                MemberInfo memberInfo1=new MemberInfo();
                memberInfo1.setId(id);
                memberInfo1.setUserId(memberOrder.getUserId());
                memberInfo1.setMemberType(memberOrder.getMemberType());
                memberInfo1.setStatus("1");
                //设置过期时间
                LocalDate newDate=null;
                switch (memberOrder.getMemberType()){
                    case "1":  newDate = nowdate.plus(4, ChronoUnit.WEEKS);
                        break;
                    case "2":  newDate = nowdate.plus(8, ChronoUnit.WEEKS);
                        break;
                }
                memberInfo1.setExpirationTime(""+newDate);
                int i = memberInfoMapper.creatInfo(memberInfo1);
                if (i != 1) {
                    return "failed";
                }
            }else if(!StringUtils.isEmpty(memberInfo)){
                //如果该用户会员信息已存在，判断是否已到期
                //如果已经过期，修改状态，在当前时间基础上加上续费时间
                LocalDate oldDate= LocalDate.parse(memberInfo.getExpirationTime());
                LocalDate newDate=null;
                if (nowdate.isAfter(oldDate)) {
                    //在当前时间上增加过期时间
                    switch (memberOrder.getMemberType()){
                        case "1":  newDate = nowdate.plus(4, ChronoUnit.WEEKS);
                            break;
                        case "2":  newDate = nowdate.plus(8, ChronoUnit.WEEKS);
                            break;
                    }
                    //修改会员为生效状态
                    memberInfo.setStatus("1");
                }else {
                    //如果未过期，在原有时间基础上增加时间
                    switch (memberOrder.getMemberType()){
                        case "1":  newDate = oldDate.plus(4, ChronoUnit.WEEKS);
                            break;
                        case "2":  newDate = oldDate.plus(8, ChronoUnit.WEEKS);
                            break;
                    }

                }
                memberInfo.setExpirationTime(""+newDate);
                int i = memberInfoMapper.updateMemberInfo(memberInfo);
                if (i != 1) {
                    return "failed";
                }
            }
            return "success";
        }else {
            return "failed";
        }
    }

    /**删除当前用户订单*/
    @Override
    public ResponseEntity deleteOrder(MemberOrder memberOrder, String userId) {
       Integer isDeleted = null;
        if(!StringUtils.isEmpty(memberOrder)){
            isDeleted=memberOrder.getIsDeleted();
        }
        int i=memberOrderMapper.deleteById(userId,isDeleted);
        if(i==1){
            return ResponseEntity.tipsSuccess(1,"删除成功");
        }
        return ResponseEntity.tipsSuccess(0,"删除失败");
    }

    /**当面付*/
    @Override
    public ResponseEntity payForMember(MemberType memberType, String userId) {
        if(!StringUtils.isEmpty(memberType)) {
            System.out.println(memberType.getId()+"-----------------------");
        }
        //查询会员类型详情
        MemberType memberTypeById=memberTypeMapper.getMemberTypeById(memberType.getId());
        //会员价格
        Double price=memberTypeById.getPrice();
        //会员价格类型id
        String type=memberType.getId();
        //生成order
        MemberOrder memberOrder=new MemberOrder();
        String id = "R" + (System.currentTimeMillis() + "" + (int) (Math.random() * 100)).substring(3);
        memberOrder.setId(id);
        memberOrder.setMemberType(type);
        memberOrder.setPrice(price);
        memberOrder.setUserId(userId);
        int i=memberOrderMapper.creatOrder(memberOrder);
        if(i!=1){
            return ResponseEntity.tipsSuccess(0, "支付宝生成订单失败");
        }
        //通过自定义类的构造方法给过期时间注入自定义时间(单位：毫秒，类型字符串)，设置订单过期时间
        rabbitTemplate.convertAndSend("delay_queue_ttl", (Object) id,new ExpiraionMessagePostProcessor("10000"));
        // (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，
        // 需保证商户系统端不能重复，建议通过数据库sequence生成，
        String outTradeNo = id ;

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = "流量圈会员扫码消费";

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = "0.1";

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0";

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
        String body = "购买商品共"+price+"元";

        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId("2088100200300400500");

        // 支付超时，定义为15分钟
        String timeoutExpress = "15m";


        // 创建扫码支付请求builder，设置请求参数
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
                .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
                .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
                .setTimeoutExpress(timeoutExpress)
                .setNotifyUrl("http://s4f6bw.natappfree.cc/member/member-info/alipay_callback.do");//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置

        //加载支付宝配置文件
        Configs.init("zfbinfo.properties");
        //提供支付宝的交易接口
        AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                System.out.println("支付宝预下单成功: )");
                AlipayTradePrecreateResponse response = result.getResponse();
                System.out.println(response.getQrCode());
                Map<String,Object> map = new HashMap<>();
                map.put("orderNo",id);
                map.put("qrPath",response.getQrCode());
                map.put("totalAmount",0.1);
                return ResponseEntity.entitySuccess(0,"",map);
            //break;

            case FAILED:
                System.out.println("支付宝预下单失败!!!");
                return ResponseEntity.tipsSuccess(1,"支付宝预下单失败!!!");
            //break;

            case UNKNOWN:
                System.out.println("系统异常，预下单状态未知!!!");
                return ResponseEntity.tipsSuccess(1,"系统异常，预下单状态未知!!!");
            //break;

            default:
                System.out.println("不支持的交易状态，交易返回异常!!!");
                return ResponseEntity.tipsSuccess(1,"不支持的交易状态，交易返回异常!!!");

            //break;
        }

    }


    /**主动查询支付宝订单状态，防止支付异常，当面付未发生请求，目的：使支付形成闭环*/
    @Override
    public ResponseEntity query_order_pay_status(MemberOrder memberOrder) {
        // (必填) 商户订单号，通过此商户订单号查询当面付的交易状态
        String outTradeNo = memberOrder.getId();

        // 创建查询请求builder，设置请求参数
        AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()
                .setOutTradeNo(outTradeNo);
        AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
        AlipayF2FQueryResult result = tradeService.queryTradeResult(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                System.out.println("查询返回该订单支付成功: )");
                //生效
                String status = "1";
                Integer i = memberOrderMapper.updateStatus(outTradeNo, status);
                AlipayTradeQueryResponse response = result.getResponse();
                System.out.println(response.getTradeStatus());
                if (Utils.isListNotEmpty(response.getFundBillList())) {
                    for (TradeFundBill bill : response.getFundBillList()) {
                        System.out.println(bill.getFundChannel() + ":" + bill.getAmount());
                    }
                }
                return ResponseEntity.tipsSuccess(0, "支付成功");

            case FAILED:
                return ResponseEntity.tipsSuccess(1, "查询返回该订单支付失败或被关闭!!!");

            case UNKNOWN:
                return ResponseEntity.tipsSuccess(1, "系统异常，订单支付状态未知!!!");

            default:
                return ResponseEntity.tipsSuccess(1, "支付失败或者未支付！");
        }


    }

}
